home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / Mail / quit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  9.9 KB  |  472 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)quit.c    5.11 (Berkeley) 1/16/89";
  20. #endif /* not lint */
  21.  
  22. #include "rcv.h"
  23. #include <sys/stat.h>
  24. #include <sys/file.h>
  25.  
  26. /*
  27.  * Rcv -- receive mail rationally.
  28.  *
  29.  * Termination processing.
  30.  */
  31.  
  32. /*
  33.  * The "quit" command.
  34.  */
  35. quitcmd()
  36. {
  37.     /*
  38.      * If we are sourcing, then return 1 so execute() can handle it.
  39.      * Otherwise, return -1 to abort command loop.
  40.      */
  41.     if (sourcing)
  42.         return 1;
  43.     return -1;
  44. }
  45.  
  46. /*
  47.  * Save all of the undetermined messages at the top of "mbox"
  48.  * Save all untouched messages back in the system mailbox.
  49.  * Remove the system mailbox, if none saved there.
  50.  */
  51.  
  52. quit()
  53. {
  54.     int mcount, p, modify, autohold, anystat, holdbit, nohold;
  55.     FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
  56.     register struct message *mp;
  57.     register int c;
  58.     extern char tempQuit[], tempResid[];
  59.     struct stat minfo;
  60.     char *mbox;
  61.  
  62.     /*
  63.      * If we are read only, we can't do anything,
  64.      * so just return quickly.
  65.      */
  66.     if (readonly)
  67.         return;
  68.     /*
  69.      * If editing (not reading system mail box), then do the work
  70.      * in edstop()
  71.      */
  72.     if (edit) {
  73.         edstop();
  74.         return;
  75.     }
  76.  
  77.     /*
  78.      * See if there any messages to save in mbox.  If no, we
  79.      * can save copying mbox to /tmp and back.
  80.      *
  81.      * Check also to see if any files need to be preserved.
  82.      * Delete all untouched messages to keep them out of mbox.
  83.      * If all the messages are to be preserved, just exit with
  84.      * a message.
  85.      */
  86.  
  87.     fbuf = fopen(mailname, "r");
  88.     if (fbuf == NULL)
  89.         goto newmail;
  90.     flock(fileno(fbuf), LOCK_EX);
  91.     rbuf = NULL;
  92.     if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
  93.         printf("New mail has arrived.\n");
  94.         rbuf = fopen(tempResid, "w");
  95.         if (rbuf == NULL || fbuf == NULL)
  96.             goto newmail;
  97. #ifdef APPEND
  98.         fseek(fbuf, mailsize, 0);
  99.         while ((c = getc(fbuf)) != EOF)
  100.             (void) putc(c, rbuf);
  101. #else
  102.         p = minfo.st_size - mailsize;
  103.         while (p-- > 0) {
  104.             c = getc(fbuf);
  105.             if (c == EOF)
  106.                 goto newmail;
  107.             (void) putc(c, rbuf);
  108.         }
  109. #endif
  110.         fclose(rbuf);
  111.         if ((rbuf = fopen(tempResid, "r")) == NULL)
  112.             goto newmail;
  113.         remove(tempResid);
  114.     }
  115.  
  116.     /*
  117.      * Adjust the message flags in each message.
  118.      */
  119.  
  120.     anystat = 0;
  121.     autohold = value("hold") != NOSTR;
  122.     holdbit = autohold ? MPRESERVE : MBOX;
  123.     nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
  124.     if (value("keepsave") != NOSTR)
  125.         nohold &= ~MSAVED;
  126.     for (mp = &message[0]; mp < &message[msgCount]; mp++) {
  127.         if (mp->m_flag & MNEW) {
  128.             mp->m_flag &= ~MNEW;
  129.             mp->m_flag |= MSTATUS;
  130.         }
  131.         if (mp->m_flag & MSTATUS)
  132.             anystat++;
  133.         if ((mp->m_flag & MTOUCH) == 0)
  134.             mp->m_flag |= MPRESERVE;
  135.         if ((mp->m_flag & nohold) == 0)
  136.             mp->m_flag |= holdbit;
  137.     }
  138.     modify = 0;
  139.     if (Tflag != NOSTR) {
  140.         if ((readstat = fopen(Tflag, "w")) == NULL)
  141.             Tflag = NOSTR;
  142.     }
  143.     for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
  144.         if (mp->m_flag & MBOX)
  145.             c++;
  146.         if (mp->m_flag & MPRESERVE)
  147.             p++;
  148.         if (mp->m_flag & MODIFY)
  149.             modify++;
  150.         if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
  151.             char *id;
  152.  
  153.             if ((id = hfield("article-id", mp)) != NOSTR)
  154.                 fprintf(readstat, "%s\n", id);
  155.         }
  156.     }
  157.     if (Tflag != NOSTR)
  158.         fclose(readstat);
  159.     if (p == msgCount && !modify && !anystat) {
  160.         printf("Held %d message%s in %s\n",
  161.             p, p == 1 ? "" : "s", mailname);
  162.         fclose(fbuf);
  163.         return;
  164.     }
  165.     if (c == 0) {
  166.         if (p != 0) {
  167.             writeback(rbuf);
  168.             fclose(fbuf);
  169.             return;
  170.         }
  171.         goto cream;
  172.     }
  173.  
  174.     /*
  175.      * Create another temporary file and copy user's mbox file
  176.      * darin.  If there is no mbox, copy nothing.
  177.      * If he has specified "append" don't copy his mailbox,
  178.      * just copy saveable entries at the end.
  179.      */
  180.  
  181.     mbox = expand("&");
  182.     mcount = c;
  183.     if (value("append") == NOSTR) {
  184.         if ((obuf = fopen(tempQuit, "w")) == NULL) {
  185.             perror(tempQuit);
  186.             fclose(fbuf);
  187.             return;
  188.         }
  189.         if ((ibuf = fopen(tempQuit, "r")) == NULL) {
  190.             perror(tempQuit);
  191.             remove(tempQuit);
  192.             fclose(obuf);
  193.             fclose(fbuf);
  194.             return;
  195.         }
  196.         remove(tempQuit);
  197.         if ((abuf = fopen(mbox, "r")) != NULL) {
  198.             while ((c = getc(abuf)) != EOF)
  199.                 (void) putc(c, obuf);
  200.             fclose(abuf);
  201.         }
  202.         if (ferror(obuf)) {
  203.             perror(tempQuit);
  204.             fclose(ibuf);
  205.             fclose(obuf);
  206.             fclose(fbuf);
  207.             return;
  208.         }
  209.         fclose(obuf);
  210.         close(creat(mbox, 0600));
  211.         if ((obuf = fopen(mbox, "r+")) == NULL) {
  212.             perror(mbox);
  213.             fclose(ibuf);
  214.             fclose(fbuf);
  215.             return;
  216.         }
  217.     }
  218.     if (value("append") != NOSTR) {
  219.         if ((obuf = fopen(mbox, "a")) == NULL) {
  220.             perror(mbox);
  221.             fclose(fbuf);
  222.             return;
  223.         }
  224.         fchmod(fileno(obuf), 0600);
  225.     }
  226.     for (mp = &message[0]; mp < &message[msgCount]; mp++)
  227.         if (mp->m_flag & MBOX)
  228.             if (send(mp, obuf, saveignore, NOSTR) < 0) {
  229.                 perror(mbox);
  230.                 fclose(ibuf);
  231.                 fclose(obuf);
  232.                 fclose(fbuf);
  233.                 return;
  234.             }
  235.  
  236.     /*
  237.      * Copy the user's old mbox contents back
  238.      * to the end of the stuff we just saved.
  239.      * If we are appending, this is unnecessary.
  240.      */
  241.  
  242.     if (value("append") == NOSTR) {
  243.         rewind(ibuf);
  244.         c = getc(ibuf);
  245.         while (c != EOF) {
  246.             (void) putc(c, obuf);
  247.             if (ferror(obuf))
  248.                 break;
  249.             c = getc(ibuf);
  250.         }
  251.         fclose(ibuf);
  252.         fflush(obuf);
  253.     }
  254.     trunc(obuf);
  255.     if (ferror(obuf)) {
  256.         perror(mbox);
  257.         fclose(obuf);
  258.         fclose(fbuf);
  259.         return;
  260.     }
  261.     fclose(obuf);
  262.     if (mcount == 1)
  263.         printf("Saved 1 message in mbox\n");
  264.     else
  265.         printf("Saved %d messages in mbox\n", mcount);
  266.  
  267.     /*
  268.      * Now we are ready to copy back preserved files to
  269.      * the system mailbox, if any were requested.
  270.      */
  271.  
  272.     if (p != 0) {
  273.         writeback(rbuf);
  274.         fclose(fbuf);
  275.         return;
  276.     }
  277.  
  278.     /*
  279.      * Finally, remove his /usr/mail file.
  280.      * If new mail has arrived, copy it back.
  281.      */
  282.  
  283. cream:
  284.     if (rbuf != NULL) {
  285.         abuf = fopen(mailname, "r+");
  286.         if (abuf == NULL)
  287.             goto newmail;
  288.         while ((c = getc(rbuf)) != EOF)
  289.             (void) putc(c, abuf);
  290.         fclose(rbuf);
  291.         trunc(abuf);
  292.         fclose(abuf);
  293.         alter(mailname);
  294.         fclose(fbuf);
  295.         return;
  296.     }
  297.     demail();
  298.     fclose(fbuf);
  299.     return;
  300.  
  301. newmail:
  302.     printf("Thou hast new mail.\n");
  303.     if (fbuf != NULL)
  304.         fclose(fbuf);
  305. }
  306.  
  307. /*
  308.  * Preserve all the appropriate messages back in the system
  309.  * mailbox, and print a nice message indicated how many were
  310.  * saved.  On any error, just return -1.  Else return 0.
  311.  * Incorporate the any new mail that we found.
  312.  */
  313. writeback(res)
  314.     register FILE *res;
  315. {
  316.     register struct message *mp;
  317.     register int p, c;
  318.     FILE *obuf;
  319.  
  320.     p = 0;
  321.     if ((obuf = fopen(mailname, "r+")) == NULL) {
  322.         perror(mailname);
  323.         return(-1);
  324.     }
  325. #ifndef APPEND
  326.     if (res != NULL)
  327.         while ((c = getc(res)) != EOF)
  328.             (void) putc(c, obuf);
  329. #endif
  330.     for (mp = &message[0]; mp < &message[msgCount]; mp++)
  331.         if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
  332.             p++;
  333.             if (send(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) {
  334.                 perror(mailname);
  335.                 fclose(obuf);
  336.                 return(-1);
  337.             }
  338.         }
  339. #ifdef APPEND
  340.     if (res != NULL)
  341.         while ((c = getc(res)) != EOF)
  342.             (void) putc(c, obuf);
  343. #endif
  344.     fflush(obuf);
  345.     trunc(obuf);
  346.     if (ferror(obuf)) {
  347.         perror(mailname);
  348.         fclose(obuf);
  349.         return(-1);
  350.     }
  351.     if (res != NULL)
  352.         fclose(res);
  353.     fsync(obuf);
  354.     fclose(obuf);
  355.     alter(mailname);
  356.     if (p == 1)
  357.         printf("Held 1 message in %s\n", mailname);
  358.     else
  359.         printf("Held %d messages in %s\n", p, mailname);
  360.     return(0);
  361. }
  362.  
  363. /*
  364.  * Terminate an editing session by attempting to write out the user's
  365.  * file from the temporary.  Save any new stuff appended to the file.
  366.  */
  367. edstop()
  368. {
  369.     register int gotcha, c;
  370.     register struct message *mp;
  371.     FILE *obuf, *ibuf, *readstat;
  372.     struct stat statb;
  373.     char tempname[30];
  374.     char *mktemp();
  375.  
  376.     if (readonly)
  377.         return;
  378.     holdsigs();
  379.     if (Tflag != NOSTR) {
  380.         if ((readstat = fopen(Tflag, "w")) == NULL)
  381.             Tflag = NOSTR;
  382.     }
  383.     for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
  384.         if (mp->m_flag & MNEW) {
  385.             mp->m_flag &= ~MNEW;
  386.             mp->m_flag |= MSTATUS;
  387.         }
  388.         if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
  389.             gotcha++;
  390.         if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
  391.             char *id;
  392.  
  393.             if ((id = hfield("article-id", mp)) != NOSTR)
  394.                 fprintf(readstat, "%s\n", id);
  395.         }
  396.     }
  397.     if (Tflag != NOSTR)
  398.         fclose(readstat);
  399.     if (!gotcha || Tflag != NOSTR)
  400.         goto done;
  401.     ibuf = NULL;
  402.     if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
  403.         strcpy(tempname, "/tmp/mboxXXXXXX");
  404.         mktemp(tempname);
  405.         if ((obuf = fopen(tempname, "w")) == NULL) {
  406.             perror(tempname);
  407.             relsesigs();
  408.             reset(0);
  409.         }
  410.         if ((ibuf = fopen(mailname, "r")) == NULL) {
  411.             perror(mailname);
  412.             fclose(obuf);
  413.             remove(tempname);
  414.             relsesigs();
  415.             reset(0);
  416.         }
  417.         fseek(ibuf, mailsize, 0);
  418.         while ((c = getc(ibuf)) != EOF)
  419.             (void) putc(c, obuf);
  420.         fclose(ibuf);
  421.         fclose(obuf);
  422.         if ((ibuf = fopen(tempname, "r")) == NULL) {
  423.             perror(tempname);
  424.             remove(tempname);
  425.             relsesigs();
  426.             reset(0);
  427.         }
  428.         remove(tempname);
  429.     }
  430.     printf("\"%s\" ", mailname);
  431.     fflush(stdout);
  432.     if ((obuf = fopen(mailname, "r+")) == NULL) {
  433.         perror(mailname);
  434.         relsesigs();
  435.         reset(0);
  436.     }
  437.     trunc(obuf);
  438.     c = 0;
  439.     for (mp = &message[0]; mp < &message[msgCount]; mp++) {
  440.         if ((mp->m_flag & MDELETED) != 0)
  441.             continue;
  442.         c++;
  443.         if (send(mp, obuf, (struct ignoretab *) NULL, NOSTR) < 0) {
  444.             perror(mailname);
  445.             relsesigs();
  446.             reset(0);
  447.         }
  448.     }
  449.     gotcha = (c == 0 && ibuf == NULL);
  450.     if (ibuf != NULL) {
  451.         while ((c = getc(ibuf)) != EOF)
  452.             (void) putc(c, obuf);
  453.         fclose(ibuf);
  454.     }
  455.     fflush(obuf);
  456.     if (ferror(obuf)) {
  457.         perror(mailname);
  458.         relsesigs();
  459.         reset(0);
  460.     }
  461.     fclose(obuf);
  462.     if (gotcha) {
  463.         remove(mailname);
  464.         printf("removed\n");
  465.     } else
  466.         printf("complete\n");
  467.     fflush(stdout);
  468.  
  469. done:
  470.     relsesigs();
  471. }
  472.